/*--------------------------------------------------------------------------------
 * Adaptive Intelligence - Foundation Framework Class Library
 * Version 2.00
 * 
 * Culture Aware Comparer Class
 *	        Compares string values based on culture-specific settings.
 *------------------------------------------------------------------------------*/

/*--------------------------------------------------------------------------------
 * System Imports
 *------------------------------------------------------------------------------*/
using System;
using System.Globalization;

namespace Adaptive.Foundation
{
    /// <summary>
    /// Compares string values based on culture-specific settings.
    /// </summary>
    [Serializable()]
    internal sealed class CultureAwareComparer : StringComparer
    {
        /*------------------------------------------------------------------------
         * Private Member Declarations
         *----------------------------------------------------------------------*/
        #region Private Member Declarations
        /// <summary>
        /// Data comparison information.
        /// </summary>
        private CompareInfo _compareInfo;
        /// <summary>
        /// Ignore casing flag.
        /// </summary>
        private bool _ignoreCase;
        #endregion

        /*------------------------------------------------------------------------
		 * Constructor / Dispose / Destructor Methods
		 *----------------------------------------------------------------------*/
        #region Constructor / Dispose / Destructor Methods
        /// <summary>
        /// Initializes a new instance of the class
        /// </summary>
        /// <remarks>
        /// This is the default constructor.
        /// </remarks>
        /// <param name="culture">
        /// A <see cref="CultureInfo"/> instance used to describe the culture/language comparison
        /// rules.
        /// </param>
        /// <param name="ignoreCase">
        /// A value indicating whether to ignore case in strings.
        /// </param>
        internal CultureAwareComparer(CultureInfo culture, bool ignoreCase)
        {
            _compareInfo = culture.CompareInfo;
            _ignoreCase = ignoreCase;
        }
        #endregion

        /*------------------------------------------------------------------------
		 * Public Methods / Functions
		 *----------------------------------------------------------------------*/
        #region Public Methods / Functions
        /// <summary>
        /// Compares two strings to determine if they are equal.
        /// </summary>
        /// <param name="x">
        /// The left-side string to be compared.
        /// </param>
        /// <param name="y">
        /// The right-side string to be compared.
        /// </param>
        /// <returns>
        /// Zero if the two strings are equal; less than zero if the left (x) string
        /// is less than the right string (y); 
        /// Greater than zero if the right string (y) is greater than the left string (x).
        /// </returns>
        public override int Compare(string x, string y)
        {
            int returnValue = 0;                //Return value.

            if (object.ReferenceEquals(x, y))
                returnValue = 0;
                
            else if (x == null)
                returnValue =  -1;
            
            else if (y == null)
                returnValue = 1;
                
            else
                returnValue = _compareInfo.Compare(x, y, _ignoreCase ? CompareOptions.IgnoreCase : CompareOptions.None);

            return returnValue;
        }
        /// <summary>
        /// Compares objects to determine if they are equal.
        /// </summary>
        /// <param name="obj">
        /// An object to compare the current instance against.
        /// </param>
        /// <returns>
        /// <b>true</b> if the two items are equal; otherwise, returns <b>false</b>.
        /// </returns>
        public override bool Equals(object obj)
        {
            CultureAwareComparer rightComparer = null;          //Right side item.
            bool returnValue = false;                           //Return value.

            //Recast item.
            rightComparer = obj as CultureAwareComparer;
            returnValue = ((rightComparer != null) && (_ignoreCase == rightComparer._ignoreCase));
            return returnValue;
        }
        /// <summary>
        /// Compares objects to determine if they are equal.
        /// </summary>
        /// <param name="x">
        /// The left-side string to be compared.
        /// </param>
        /// <param name="y">
        /// The right-side string to be compared.
        /// </param>
        /// <returns>
        /// <b>true</b> if the two items are equal; otherwise, returns <b>false</b>.
        /// </returns>
        public override bool Equals(string x, string y)
        {
            bool returnValue = false;               //Return value.

            returnValue = (Compare(x,y) == 0);
            return returnValue;
        }
        /// <summary>
        /// Gets a hash code value for the current object instance.
        /// </summary>
        /// <returns>
        /// A hash code value.
        /// </returns>
        public override int GetHashCode()
        {
            int returnValue = 0;                //Return value.

            returnValue = _compareInfo.GetHashCode();
            if (_ignoreCase)
                returnValue = ~returnValue;
            return returnValue;
        }
        /// <summary>
        /// Gets a hash code value for the specified string instance.
        /// </summary>
        /// <returns>
        /// A hash code value.
        /// </returns>
        public override int GetHashCode(string obj)
        {
            int returnValue = 0;                //Return value.

            if (obj == null)
            {
                throw new ArgumentNullException("obj");
            }
            if (_ignoreCase)
                returnValue = _compareInfo.GetHashCode();
            else
                returnValue = obj.GetHashCode();

            return returnValue;
        }
        #endregion
    }
}